package com.ikingtech.platform.service.wechat.mini.controller;

import com.ikingtech.framework.sdk.context.exception.FrameworkException;
import com.ikingtech.framework.sdk.core.response.R;
import com.ikingtech.framework.sdk.utils.Tools;
import com.ikingtech.framework.sdk.web.annotation.ApiController;
import com.ikingtech.framework.sdk.wechat.embedded.mini.*;
import com.ikingtech.framework.sdk.wechat.embedded.mini.resposne.WechatMiniResponseSession;
import com.ikingtech.framework.sdk.wechat.embedded.properties.WechatProperties;
import com.ikingtech.framework.sdk.wechat.mini.api.WechatMiniApi;
import com.ikingtech.framework.sdk.wechat.mini.model.*;
import com.ikingtech.platform.service.wechat.mini.entity.WechatMiniDO;
import com.ikingtech.platform.service.wechat.mini.exception.WechatMiniExceptionInfo;
import com.ikingtech.platform.service.wechat.mini.service.WechatMiniService;
import com.ikingtech.framework.sdk.wechat.mini.model.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * @author tie yan
 */
@Slf4j
@RequiredArgsConstructor
@ApiController(value = "/wechat/mini", name = "微信管理-微信小程序管理", description = "微信管理-微信小程序管理")
public class WechatMiniController implements WechatMiniApi {

    private final WechatMiniService service;

    private final WechatProperties properties;

    private final WechatMiniRequestBuilder wechatMiniRequestBuilder;

    @Override
    public R<String> add(WechatMiniDTO wechatMini) {
        if (Boolean.TRUE.equals(this.service.nameExist(wechatMini.getName()))) {
            throw new FrameworkException(WechatMiniExceptionInfo.DUPLICATE_WECHAT_MINI_NAME);
        }
        if (Boolean.TRUE.equals(this.service.appIdExist(wechatMini.getAppId()))) {
            throw new FrameworkException(WechatMiniExceptionInfo.DUPLICATE_WECHAT_MINI_APP_ID);
        }

        WechatMiniDO entity = Tools.Bean.copy(wechatMini, WechatMiniDO.class);
        entity.setId(Tools.Id.uuid());
        entity.setCode(entity.getId());
        this.service.save(entity);
        return R.ok(entity.getId());
    }

    @Override
    public R<Object> delete(String id) {
        this.service.removeById(id);
        return R.ok();
    }

    @Override
    public R<Object> update(WechatMiniDTO wechatMini) {
        if (!Boolean.TRUE.equals(this.service.exist(wechatMini.getId()))) {
            throw new FrameworkException(WechatMiniExceptionInfo.WECHAT_MINI_NOT_FOUND);
        }
        if (Boolean.TRUE.equals(this.service.nameExist(wechatMini.getId(), wechatMini.getName()))) {
            throw new FrameworkException(WechatMiniExceptionInfo.DUPLICATE_WECHAT_MINI_NAME);
        }
        if (Boolean.TRUE.equals(this.service.appIdExist(wechatMini.getId(), wechatMini.getAppId()))) {
            throw new FrameworkException(WechatMiniExceptionInfo.DUPLICATE_WECHAT_MINI_APP_ID);
        }

        this.service.updateById(Tools.Bean.copy(wechatMini, WechatMiniDO.class));
        return R.ok();
    }

    @Override
    public R<List<WechatMiniDTO>> page(WechatMiniQueryParamDTO queryParam) {
        return R.ok(this.service.listPage(queryParam).convert(entity -> Tools.Bean.copy(entity, WechatMiniDTO.class)));
    }

    @Override
    public R<List<WechatMiniDTO>> all() {
        List<WechatMiniDTO> result = Tools.Coll.convertList(this.service.list(), entity -> Tools.Bean.copy(entity, WechatMiniDTO.class));
        result.addAll(Tools.Coll.convertList(this.properties.getMini(), wechatMiniInfo -> {
            WechatMiniDTO wechatMini = Tools.Bean.copy(wechatMiniInfo, WechatMiniDTO.class);
            wechatMini.setId(Tools.Id.uuid());
            wechatMini.setCode(wechatMiniInfo.getId());
            return wechatMini;
        }));
        return R.ok(result);
    }

    @Override
    public R<WechatMiniDTO> detail(String id) {
        WechatMiniDO entity = this.service.getById(id);
        if (null == entity) {
            throw new FrameworkException(WechatMiniExceptionInfo.WECHAT_MINI_NOT_FOUND);
        }
        return R.ok(Tools.Bean.copy(entity, WechatMiniDTO.class));
    }

    @Override
    public R<Object> sendSubscribeMessage(WechatMiniSendMessageParamDTO sendMessageParam) {
        this.wechatMiniRequestBuilder.build(this.loadConfig(sendMessageParam.getWechatMiniId()))
                .sendSubscribeMessage(WechatMiniSendSubscribeMessageArgs.builder()
                        .templateId(sendMessageParam.getTemplateId())
                        .openId(sendMessageParam.getOpenId())
                        .redirectTo(sendMessageParam.getRedirectTo())
                        .params(sendMessageParam.getParam())
                        .build());
        return R.ok();
    }

    @Override
    public R<WechatMiniUserInfoDTO> exchangeCode(WechatMiniExchangeCodeParamDTO exchangeCodeParam) {
        WechatMiniResponseSession wechatMiniSessionInfo = this.wechatMiniRequestBuilder.build(this.loadConfig(exchangeCodeParam.getWechatMiniId())).exchangeCode(exchangeCodeParam.getCode());
        WechatMiniUserInfoDTO userInfo = new WechatMiniUserInfoDTO();
        userInfo.setUnionId(wechatMiniSessionInfo.getUnionid());
        userInfo.setOpenid(wechatMiniSessionInfo.getOpenid());
        userInfo.setSessionKey(wechatMiniSessionInfo.getSessionKey());
        return R.ok(userInfo);
    }

    @Override
    public R<WechatMiniPhoneDTO> getPhoneByCode(WechatMiniPhoneQueryParamDTO queryParam) {
        WechatMiniUserPhoneInfo userPhoneInfo = this.wechatMiniRequestBuilder.build(this.loadConfig(queryParam.getWechatMiniId())).getPhone(queryParam.getCode());
        WechatMiniPhoneDTO phone = new WechatMiniPhoneDTO();
        phone.setPhoneNo(userPhoneInfo.getPhone());
        phone.setPurePhoneNo(userPhoneInfo.getPurePhone());
        phone.setCountryCode(userPhoneInfo.getCountryCode());
        return R.ok(phone);
    }

    @Override
    public R<String> qrcode(WechatMiniQrcodeGenerateParamDTO generateParam) {
        String qrcodeBase64Str = this.wechatMiniRequestBuilder.build(this.loadConfig(generateParam.getWechatMiniId()))
                .qrcodeGenerate(WechatMiniQrcodeGenerateArgs.builder()
                        .page(generateParam.getPage())
                        .width(generateParam.getWidth())
                        .param(generateParam.getParam())
                        .version(generateParam.getVersion())
                        .build());
        return R.ok(qrcodeBase64Str);
    }

    @Override
    public R<String> urlLink(WechatMiniUrlLinkGenerateParamDTO generateParam) {
        String urlLink = this.wechatMiniRequestBuilder.build(this.loadConfig(generateParam.getWechatMiniId()))
                .urlLinkGenerate(WechatMiniUrlLinkGenerateArgs.builder()
                        .page(generateParam.getPage())
                        .param(generateParam.getParam())
                        .build());
        return R.ok(urlLink);
    }


    @Override
    public R<List<WechatMiniSubscribeMessageTemplateDTO>> listSubscribeMessageTemplate(String wechatMiniId) {
        List<WechatMiniSubscribeMessageTemplateInfo> messageTemplates = this.wechatMiniRequestBuilder.build(this.loadConfig(wechatMiniId)).listSubscribeMessageTemplate();
        return R.ok(Tools.Coll.convertList(messageTemplates, templateInfo -> {
            WechatMiniSubscribeMessageTemplateDTO template = new WechatMiniSubscribeMessageTemplateDTO();
            template.setId(templateInfo.getTemplateId());
            template.setWechatMiniId(wechatMiniId);
            template.setName(templateInfo.getTemplateTitle());
            template.setTitle(templateInfo.getTemplateTitle());
            template.setContent(templateInfo.getContent());
            template.setType(templateInfo.getType());
            template.setTypeName(templateInfo.getType().description);
            template.setParams(templateInfo.getParams());
            return template;
        }));
    }

    private WechatMiniConfig loadConfig(String wechatMiniId) {
        WechatMiniDO entity = this.service.getById(wechatMiniId);
        if (null == entity) {
            return Tools.Bean.copy(this.getFromProperties(wechatMiniId), WechatMiniConfig.class);
        } else {
            return Tools.Bean.copy(entity, WechatMiniConfig.class);
        }
    }

    private WechatMiniConfig getFromProperties(String wechatMiniId) {
        for (WechatProperties.WechatMini wechatMini : this.properties.getMini()) {
            if (Tools.Str.equals(wechatMiniId, wechatMini.getId())) {
                return Tools.Bean.copy(wechatMini, WechatMiniConfig.class);
            }
        }
        throw new FrameworkException("微信小程序配置不存在");
    }
}
